-- CraftOS+ Server Startup By Sirharry0077

oldpullEvent = os.pullEvent
os.pullEvent = os.pullEventRaw

shell.run("clear")

local function zfill(N)
	N=string.format("%X",N)
	Zs=""
	if #N==1 then
		Zs="0"
	end
	return Zs..N
end

local function serializeImpl(t)	
	local sType = type(t)
	if sType == "table" then
		local lstcnt=0
		for k,v in pairs(t) do
			lstcnt = lstcnt + 1
		end
		local result = "{"
		local aset=1
		for k,v in pairs(t) do
			if k==aset then
				result = result..serializeImpl(v)..","
				aset=aset+1
			else
				result = result..("["..serializeImpl(k).."]="..serializeImpl(v)..",")
			end
		end
		result = result.."}"
		return result
	elseif sType == "string" then
		return string.format("%q",t)
	elseif sType == "number" or sType == "boolean" or sType == "nil" then
		return tostring(t)
	elseif sType == "function" then
		local status,data=pcall(string.dump,t)
		if status then
			return 'func('..string.format("%q",data)..')'
		else
			error()
		end
	else
		error()
	end
end

local function split(T,func)
	if func then
		T=func(T)
	end
	local Out={}
	if type(T)=="table" then
		for k,v in pairs(T) do
			Out[split(k)]=split(v)
		end
	else
		Out=T
	end
	return Out
end

local function serialize( t )
	t=split(t)
	return serializeImpl( t, tTracking )
end

local function unserialize( s )
	local func, e = loadstring( "return "..s, "serialize" )
	local funcs={}
	if not func then
		return e
	end
	setfenv( func, {
		func=function(S)
			local new={}
			funcs[new]=S
			return new
		end,
	})
	return split(func(),function(val)
		if funcs[val] then
			return loadstring(funcs[val])
		else
			return val
		end
	end)
end

local function sure(N,n)
	if (l2-n)<1 then N="0" end
	return N
end

local function splitnum(S)
	Out=""
	for l1=1,#S,2 do
		l2=(#S-l1)+1
		CNum=tonumber("0x"..sure(string.sub(S,l2-1,l2-1),1) .. sure(string.sub(S,l2,l2),0))
		Out=string.char(CNum)..Out
	end
	return Out
end

local function wrap(N)
	return N-(math.floor(N/256)*256)
end

function checksum(S,num)
	local sum=0
	for char in string.gmatch(S,".") do
		for l1=1,(num or 1) do
			math.randomseed(string.byte(char)+sum)
			sum=sum+math.random(0,9999)
		end
	end
	math.randomseed(sum)
	return sum
end

local function genkey(len,psw)
	checksum(psw)
	local key={}
	local tKeys={}
	for l1=1,len do
		local num=math.random(1,len)
		while tKeys[num] do
			num=math.random(1,len)
		end
		tKeys[num]=true
		key[l1]={num,math.random(0,255)}
	end
	return key
end

function encrypt(data,psw)
	data=serialize(data)
	local chs=checksum(data)
	local key=genkey(#data,psw)
	local out={}
	local cnt=1
	for char in string.gmatch(data,".") do
		table.insert(out,key[cnt][1],zfill(wrap(string.byte(char)+key[cnt][2])),chars)
		cnt=cnt+1
	end
	return string.sub(serialize({chs,table.concat(out)}),2,-3)
end

function decrypt(data,psw)
	local oData=data
	data=unserialize("{"..data.."}")
	if type(data)~="table" then
		return oData
	end
	local chs=data[1]
	data=data[2]
	local key=genkey((#data)/2,psw)
	local sKey={}
	for k,v in pairs(key) do
		sKey[v[1]]={k,v[2]}
	end
	local str=splitnum(data)
	local cnt=1
	local out={}
	for char in string.gmatch(str,".") do
		table.insert(out,sKey[cnt][1],string.char(wrap(string.byte(char)-sKey[cnt][2])))
		cnt=cnt+1
	end
	out=table.concat(out)
	if checksum(out or "")==chs then
		return unserialize(out)
	end
	return oData,out,chs
end

local function openRednet()
local listOfSides = rs.getSides()
local listofPossibles = {}
local counter1 = 0
while true do
  counter1 = counter1 +1

  if peripheral.isPresent(tostring(listOfSides[counter1])) and peripheral.getType(listOfSides[counter1]) == "modem" then
   table.insert(listofPossibles,tostring(listOfSides[counter1]))
  end

  if counter1 == 6 and table.maxn(listofPossibles) == 0 then
   print("no wifi present")
   return nil
  end

  if counter1 == 6 and table.maxn(listofPossibles) ~= 0 then
   rednet.open(listofPossibles[1])
   return listofPossibles[1]
  end
end
end
modemOn = openRednet()
openRednet()

shell.run("clear")
if fs.exists("programs/version") == false then
 print("ERROR No Version File")
 sleep(1)
else
 file = fs.open("programs/version", "r")
 version = file.readLine()
 file.close()
end

if fs.exists("bin/username") == false or fs.exists("bin/password") == false then
 shell.run("clear")
 print("Welcome To CraftOS+ Server")
 print("--------------------------")
 print("Please Follow These Few Simple Steps To Get Your Server Up and Running.")
 print("Press ENTER To Proceed")
 read()
 fs.makeDir("bin")
end
 
if fs.exists("bin/username") == false then
 shell.run("clear")
 print("Create Username")
 print("---------------")
 write("Username: ")
 newusername = read()
 fs.makeDir("bin")
 file = fs.open("bin/username", "w")
 file.write(newusername)
 file.close()
end

if fs.exists("bin/password") == false then
 shell.run("clear")
 print("Create Password")
 print("---------------")
 write("Password: ")
 newpassword = read("*")
 newpassword1 = encrypt(newpassword, newpassword)
 fs.makeDir("bin")
 file = fs.open("bin/password", "w")
 file.write(newpassword1)
 file.close()
end

if fs.exists("bin/admins") == false then
 shell.run("clear")
 print("Create Admin Computer")
 print("---------------------")
 print("This Is The CraftOS+ Computer That You Want To Have Admin Privilages.  You Can Add More Admins Later.")
 write("Admin ID: ")
 newadmin = read()
 fs.makeDir("bin")
 file = fs.open("bin/admins", "w")
 file.write(newadmin)
 file.close()
end

shell.run("clear")
shell.run("server")

shell.run("clear")
file = fs.open("bin/password", "r")
encryptedPassword = file.readLine()
file.close()
file = fs.open("bin/username", "r")
user = file.readLine()
file.close()

shell.run("clear")
print("CraftOS+ Server ", version)
print("-------------------")
write("Password: ")
text = read("*")
text = encrypt(text, text)
if text == encryptedPassword then
 shell.run("clear")
 print("CraftOS+ Server ", version)
 print("-------------------")
 print("Welcome To Admin Controls")
 print("You Can Directly Edit Server Files With The EDIT Command.  For More Help Type HELP.")
 
 cid = os.getComputerID()
 label = user.."'s Server | ID "..cid
 os.setComputerLabel(label)
else
 os.reboot()
end
